package com.ollobot.authorization.controller;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.ollobot.authorization.common.ErrorCode;
import com.ollobot.authorization.common.TimestampResponseEntity;
import com.ollobot.authorization.dto.EmailVerificationRequest;
import com.ollobot.authorization.dto.GoogleTokenRequest;
import com.ollobot.authorization.dto.LoginResponse;
import com.ollobot.authorization.dto.RefreshTokenRequest;
import com.ollobot.authorization.dto.RegisterRequest;
import com.ollobot.authorization.dto.SendCodeRequest;
import com.ollobot.authorization.dto.TokenRefreshResponse;
import com.ollobot.authorization.dto.TokenResponse;
import com.ollobot.authorization.dto.TokenValidationResponse;
import com.ollobot.authorization.dto.UsernamePasswordLoginRequest;
import com.ollobot.authorization.entity.User;
import com.ollobot.authorization.exception.RateBeyondException;
import com.ollobot.authorization.security.EmailVerificationAuthenticationToken;
import com.ollobot.authorization.service.EmailVerificationService;
import com.ollobot.authorization.service.GoogleTokenVerificationService;
import com.ollobot.authorization.service.JwtTokenService;
import com.ollobot.authorization.service.UserService;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
@Slf4j
public class AuthController {

    private final EmailVerificationService emailVerificationService;
    private final GoogleTokenVerificationService googleTokenVerificationService;
    private final UserService userService;
    private final JwtTokenService jwtTokenService;
    private final AuthenticationManager authenticationManager;

    @PostMapping("/send-code")
    public TimestampResponseEntity<Void> sendVerificationCode(@Valid @RequestBody SendCodeRequest request) {
        try {
            emailVerificationService.generateAndSendCode(request.getEmail());

            return new TimestampResponseEntity<>(null, org.springframework.http.HttpStatus.OK,
                    "Verification code sent successfully");
        } catch (RateBeyondException ex) {
            throw ex;
        } catch (Exception e) {
            log.error("Failed to send verification code", e);
            return TimestampResponseEntity.<Void>error(ErrorCode.EMAIL_SEND_FAILED, e.getMessage());
        }
    }

    @PostMapping("/verify-email")
    public TimestampResponseEntity<LoginResponse> verifyEmail(@Valid @RequestBody EmailVerificationRequest request) {
        try {

            EmailVerificationAuthenticationToken authToken = new EmailVerificationAuthenticationToken(
                    request.getEmail(),
                    request.getCode(),
                    request.getFirstName(),
                    request.getLastName());

            Authentication authentication = authenticationManager.authenticate(authToken);
            SecurityContextHolder.getContext().setAuthentication(authentication);

            // 获取认证后的用户信息
            User user = (User) authentication.getPrincipal();

            // 生成JWT token对
            TokenResponse tokens = jwtTokenService.generateTokenPair(user);

            log.info("Email verification successful for user: {}", user.getEmail());

            // 构建响应对象
            LoginResponse loginResponse = LoginResponse.builder()
                    .tokens(tokens)
                    .user(LoginResponse.UserInfo.builder()
                            .id(user.getId())
                            .email(user.getEmail())
                            .firstName(user.getFirstName())
                            .lastName(user.getLastName())
                            .avatarUrl(user.getAvatarUrl())
                            .provider(user.getProvider().name())
                            .build())
                    .build();

            return new TimestampResponseEntity<>(loginResponse, org.springframework.http.HttpStatus.OK,
                    "Email verification successful");
        } catch (Exception e) {
            log.error("Email verification failed", e);
            return TimestampResponseEntity.<LoginResponse>error(ErrorCode.VERIFICATION_CODE_INVALID,
                    "Invalid verification code");
        }
    }

    @PostMapping("/google-token")
    public TimestampResponseEntity<LoginResponse> googleTokenLogin(@Valid @RequestBody GoogleTokenRequest request,
            @RequestHeader("token") String token) {
        try {
            // 验证Google ID Token
            GoogleIdToken.Payload payload = googleTokenVerificationService.verifyToken(token);

            // 从token中获取用户信息
            String email = payload.getEmail();
            String firstName = (String) payload.get("given_name");
            String lastName = (String) payload.get("family_name");
            String picture = (String) payload.get("picture");
            String googleUserId = payload.getSubject();

            // 如果请求中提供了姓名，优先使用请求中的
            if (request.getFirstName() != null && !request.getFirstName().isEmpty()) {
                firstName = request.getFirstName();
            }
            if (request.getLastName() != null && !request.getLastName().isEmpty()) {
                lastName = request.getLastName();
            }

            // 创建或更新用户
            User user = userService.createOrUpdateOAuthUser(
                    email,
                    firstName,
                    lastName,
                    picture,
                    User.AuthProvider.GOOGLE,
                    googleUserId);

            // 创建认证对象并设置到安全上下文
            Authentication authentication = new EmailVerificationAuthenticationToken(
                    user, null, user.getAuthorities(), email, null, firstName, lastName);
            SecurityContextHolder.getContext().setAuthentication(authentication);

            // 生成JWT token对
            TokenResponse tokens = jwtTokenService.generateTokenPair(user);

            log.info("Google token login successful for user: {}", email);

            // 构建响应对象
            LoginResponse loginResponse = LoginResponse.builder()
                    .tokens(tokens)
                    .user(LoginResponse.UserInfo.builder()
                            .id(user.getId())
                            .email(user.getEmail())
                            .firstName(user.getFirstName())
                            .lastName(user.getLastName())
                            .avatarUrl(user.getAvatarUrl())
                            .provider(user.getProvider().name())
                            .build())
                    .build();

            return new TimestampResponseEntity<>(loginResponse, org.springframework.http.HttpStatus.OK,
                    "Google login successful");
        } catch (Exception e) {
            log.error("Google token login failed", e);
            return TimestampResponseEntity.<LoginResponse>error(ErrorCode.GOOGLE_TOKEN_INVALID,
                    "Invalid Google token: " + e.getMessage());
        }
    }

    @PostMapping("/refresh-token")
    public TimestampResponseEntity<TokenRefreshResponse> refreshToken(@Valid @RequestBody RefreshTokenRequest request,
            @RequestHeader("token") String token) {
        try {
            // 从refresh token中获取用户ID
            Long userId = jwtTokenService.getUserIdFromToken(token);

            // 根据用户ID获取用户信息
            User user = userService.findById(userId)
                    .orElseThrow(() -> new RuntimeException("User not found"));

            // 刷新访问令牌
            String newAccessToken = jwtTokenService.refreshAccessToken(token, user);

            // 计算新的过期时间戳
            long expiresAt = System.currentTimeMillis() + 3600 * 1000; // 1小时后过期

            log.info("Token refreshed for user: {}", user.getEmail());

            // 构建响应对象
            TokenRefreshResponse tokenResponse = TokenRefreshResponse.builder()
                    .accessToken(newAccessToken)
                    .tokenType("Bearer")
                    .expiresIn(3600)
                    .expiresAt(expiresAt)
                    .build();

            return new TimestampResponseEntity<>(tokenResponse, org.springframework.http.HttpStatus.OK,
                    "Token refreshed successfully");
        } catch (Exception e) {
            log.error("Token refresh failed", e);
            return TimestampResponseEntity.<TokenRefreshResponse>error(ErrorCode.REFRESH_TOKEN_INVALID,
                    "Invalid refresh token: " + e.getMessage());
        }
    }

    @PostMapping("/register")
    public TimestampResponseEntity<LoginResponse> register(@Valid @RequestBody RegisterRequest request) {
        try {
            // 注册新用户
            User user = userService.registerUser(
                    request.getUsername(),
                    request.getEmail(),
                    request.getPassword(),
                    request.getFirstName(),
                    request.getLastName());

            // 自动登录新注册的用户
            UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                    request.getUsername(),
                    request.getPassword());

            Authentication authentication = authenticationManager.authenticate(authToken);
            SecurityContextHolder.getContext().setAuthentication(authentication);

            // 生成JWT token对
            TokenResponse tokens = jwtTokenService.generateTokenPair(user);

            log.info("User registration and login successful for user: {}", user.getUsername());

            // 构建响应对象
            LoginResponse loginResponse = LoginResponse.builder()
                    .tokens(tokens)
                    .user(LoginResponse.UserInfo.builder()
                            .id(user.getId())
                            .email(user.getEmail())
                            .firstName(user.getFirstName())
                            .lastName(user.getLastName())
                            .avatarUrl(user.getAvatarUrl())
                            .provider(user.getProvider().name())
                            .build())
                    .build();

            return new TimestampResponseEntity<>(loginResponse, org.springframework.http.HttpStatus.CREATED,
                    "Registration successful");
        } catch (Exception e) {
            log.error("User registration failed", e);
            if (e.getMessage().contains("Username already exists")) {
                return TimestampResponseEntity.<LoginResponse>error(ErrorCode.USER_ALREADY_EXISTS,
                        "Username already exists");
            } else if (e.getMessage().contains("Email already exists")) {
                return TimestampResponseEntity.<LoginResponse>error(ErrorCode.USER_ALREADY_EXISTS,
                        "Email already exists");
            } else {
                return TimestampResponseEntity.<LoginResponse>error(ErrorCode.USER_CREATION_FAILED,
                        "Registration failed: " + e.getMessage());
            }
        }
    }

    @PostMapping("/login")
    public TimestampResponseEntity<LoginResponse> usernamePasswordLogin(
            @Valid @RequestBody UsernamePasswordLoginRequest request) {
        try {
            // 创建用户名密码认证令牌
            UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                    request.getUsername(),
                    request.getPassword());

            // 进行认证
            Authentication authentication = authenticationManager.authenticate(authToken);
            SecurityContextHolder.getContext().setAuthentication(authentication);

            // 获取认证后的用户信息
            User user = (User) authentication.getPrincipal();

            // 生成JWT token对
            TokenResponse tokens = jwtTokenService.generateTokenPair(user);

            log.info("Username/password login successful for user: {}", user.getUsername());

            // 构建响应对象
            LoginResponse loginResponse = LoginResponse.builder()
                    .tokens(tokens)
                    .user(LoginResponse.UserInfo.builder()
                            .id(user.getId())
                            .email(user.getEmail())
                            .firstName(user.getFirstName())
                            .lastName(user.getLastName())
                            .avatarUrl(user.getAvatarUrl())
                            .provider(user.getProvider().name())
                            .build())
                    .build();

            return new TimestampResponseEntity<>(loginResponse, org.springframework.http.HttpStatus.OK,
                    "Login successful");
        } catch (Exception e) {
            log.error("Username/password login failed", e);
            return TimestampResponseEntity.<LoginResponse>error(ErrorCode.INVALID_CREDENTIALS,
                    "Invalid username or password");
        }
    }

    @PostMapping("/logout")
    public TimestampResponseEntity<Void> logout(
            @RequestHeader(value = "Authorization", required = false) String authHeader) {
        try {
            if (authHeader != null && authHeader.startsWith("Bearer ")) {
                String token = authHeader.substring(7);
                Long userId = jwtTokenService.getUserIdFromToken(token);

                // 撤销用户的refresh token
                jwtTokenService.revokeRefreshToken(userId);

                log.info("User logged out: {}", userId);
            }

            // 清除安全上下文
            SecurityContextHolder.clearContext();

            return new TimestampResponseEntity<>(null, org.springframework.http.HttpStatus.OK, "Logout successful");
        } catch (Exception e) {
            log.error("Logout failed", e);
            return new TimestampResponseEntity<>(null, org.springframework.http.HttpStatus.OK, "Logout completed");
        }
    }

    @PostMapping("/deactivate-account")
    public TimestampResponseEntity<Void> deactivateAccount(@RequestHeader("Authorization") String authHeader) {
        try {
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                return TimestampResponseEntity.<Void>error(ErrorCode.INVALID_CREDENTIALS,
                        "Invalid authorization header");
            }

            String token = authHeader.substring(7);
            Long userId = jwtTokenService.getUserIdFromToken(token);

            // 软删除用户账户（禁用账户）
            userService.deleteUser(userId);

            // 撤销用户的所有token
            jwtTokenService.revokeRefreshToken(userId);

            // 清除安全上下文
            SecurityContextHolder.clearContext();

            log.info("User account deactivated: {}", userId);

            return new TimestampResponseEntity<>(null, org.springframework.http.HttpStatus.OK,
                    "Account deactivated successfully");
        } catch (Exception e) {
            log.error("Account deactivation failed", e);
            return TimestampResponseEntity.<Void>error(ErrorCode.USER_CREATION_FAILED,
                    "Account deactivation failed: " + e.getMessage());
        }
    }

    @PostMapping("/delete-account")
    public TimestampResponseEntity<Void> deleteAccount(@RequestHeader("Authorization") String authHeader) {
        try {
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                return TimestampResponseEntity.<Void>error(ErrorCode.INVALID_CREDENTIALS,
                        "Invalid authorization header");
            }

            String token = authHeader.substring(7);
            Long userId = jwtTokenService.getUserIdFromToken(token);

            // 撤销用户的所有token
            jwtTokenService.revokeRefreshToken(userId);

            // 永久删除用户账户
            userService.permanentDeleteUser(userId);

            // 清除安全上下文
            SecurityContextHolder.clearContext();

            log.info("User account permanently deleted: {}", userId);

            return new TimestampResponseEntity<>(null, org.springframework.http.HttpStatus.OK,
                    "Account deleted permanently");
        } catch (Exception e) {
            log.error("Account deletion failed", e);
            return TimestampResponseEntity.<Void>error(ErrorCode.USER_CREATION_FAILED,
                    "Account deletion failed: " + e.getMessage());
        }
    }

    /**
     * 验证token有效性接口
     * 用于k8s中其他服务调用检查token有效性
     */
    @PostMapping("/validate-token")
    public TimestampResponseEntity<TokenValidationResponse> validateToken(
            @RequestHeader("Authorization") String authHeader) {
        try {
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                TokenValidationResponse response = TokenValidationResponse.builder()
                        .valid(false)
                        .errorMessage("Invalid authorization header format")
                        .build();
                return new TimestampResponseEntity<>(response, org.springframework.http.HttpStatus.BAD_REQUEST,
                        "Invalid authorization header");
            }

            String token = authHeader.substring(7);

            // 获取token详细信息
            Map<String, Object> tokenDetails = jwtTokenService.getTokenDetails(token);

            // 构建响应对象
            TokenValidationResponse.TokenValidationResponseBuilder responseBuilder = TokenValidationResponse.builder();

            Boolean isValid = (Boolean) tokenDetails.get("valid");
            responseBuilder.valid(isValid != null ? isValid : false);

            if (isValid != null && isValid) {
                // Token有效，填充用户信息
                responseBuilder
                        .userId((Long) tokenDetails.get("userId"))
                        .email((String) tokenDetails.get("email"))
                        .username((String) tokenDetails.get("username"))
                        .provider((String) tokenDetails.get("provider"))
                        .emailVerified((Boolean) tokenDetails.get("emailVerified"))
                        .tokenType((String) tokenDetails.get("tokenType"))
                        .expiresAt((Long) tokenDetails.get("expiresAt"));

                log.info("Token validation successful for user: {}", tokenDetails.get("email"));

                return new TimestampResponseEntity<>(responseBuilder.build(), org.springframework.http.HttpStatus.OK,
                        "Token is valid");
            } else {
                // Token无效
                String errorMessage = (String) tokenDetails.get("errorMessage");
                responseBuilder.errorMessage(errorMessage != null ? errorMessage : "Token is invalid or expired");

                log.warn("Token validation failed: {}", errorMessage);

                return new TimestampResponseEntity<>(responseBuilder.build(),
                        org.springframework.http.HttpStatus.UNAUTHORIZED, "Token is invalid");
            }

        } catch (Exception e) {
            log.error("Token validation error", e);

            TokenValidationResponse response = TokenValidationResponse.builder()
                    .valid(false)
                    .errorMessage("Token validation failed: " + e.getMessage())
                    .build();

            return new TimestampResponseEntity<>(response, org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR,
                    "Token validation error");
        }
    }
}
